; 这里是boot和loader的公共函数，就不需要在两边都写了。
; 这个代码要能运行，需要在引用本文件的地方定义如下数据：
; 1、wSectorNo dw类型 查找文件时存放扇区号
; 2、bOdd db类型 存放扇区号是奇数还是偶数



; 函数功能：根据名称在FAT根目录中查找文件
; 参数1：文件名的其实地址
; 返回参数：
; 0：找到
; 1: 未找到
findInRootDir:
	mov bp, sp
	mov word [wSectorNo], SectorNoOfRootDirectory
findInSector:
	; 这里采用了跟于老师不同的方式，于老师定义了一个wRootDirSizeForLoop变量，这里是直接比较wSectorNo
	cmp word [wSectorNo], SectorNoOfRootDirectoryEnd
	ja notFound
	; 获取参数3，即Sector存放地址段基址
	mov ax, BaseOfLoadFile
	mov es, ax
	; 获取参数2
	mov bx, OffsetOfLoadFile
	push word [wSectorNo]
	push 1
	call ReadSector
	add sp, 4
	
	; 第一个参数，即文件名字
	mov si, word [bp + 2]
	mov di, OffsetOfLoadFile
	cld
	mov dx, 10h
compareFileItem:
	cmp dx, 0
	jz findInNextSector
	dec dx
	mov cx, 11
compareFileName:
	cmp cx, 0
	jz found
	dec cx
	lodsb
	cmp al, [es:di]
	jz goOnCompare
	jmp different
	
goOnCompare:
	inc di
	jmp compareFileName
	
different:
	and di, 0FFE0h
	add di, 20h
	mov si, word [bp + 2]
	jmp compareFileItem
	
findInNextSector:
	add word [wSectorNo], 1
	jmp findInSector
	
found:
	mov ax, 0
	jmp completeAndRet
	
notFound:
	mov ax, 1
	jmp completeAndRet
	
completeAndRet:
	ret

	
; 函数功能：输出一行字符串
; 参数1：字符串首地址
DispStr:
	mov bp, sp
	mov cx, 9
	mov bp, word [bp + 2]
	mov ax, ds
	mov es, ax
	mov ax, 01301h
	mov bx, 0007h
	mov dl, 0
	int 10h
	ret

; 函数功能：读取扇区
; 参数1：扇区号
; 参数2：扇区数目
ReadSector:
	push bp
	mov bp, sp
	
	push bx
	; 第一个参数，扇区号
	mov ax, [bp + 6]
%ifdef _IN_BOOT_
	mov bl, byte [BPB_SecPerTrk]
%else
	mov bl, BPB_SecPerTrk
%endif
	div bl
	
	mov ch, al
	shr ch, 1
	mov dh, al
	and dh, 1
	
	mov cl, ah
	inc cl
	pop bx
%ifdef _IN_BOOT_
	mov dl, byte [BS_DrvNum]
%else
	mov dl, BS_DrvNum
%endif
.GoOnReading:	
	mov ah, 02h
	mov al, byte [bp + 4]
	int 13h
	jc .GoOnReading
	
	pop bp
	ret
	
; 从第一个扇区开始读取整个文件
; 参数1：起始扇区
ReadFileByFirstSector:
	mov bp, sp
	push es
	
	mov ax, BaseOfLoadFile
	mov es, ax
	mov bx, OffsetOfLoadFile
	; 参数1：起始扇区号，其实是个簇号，需要加上DeltaSectorNo和RootDirSectors才能得到真实的扇区
	mov ax, [bp + 2]
	push ax
	add ax, RootDirSectors
	add ax, DeltaSectorNo
GoOnLoadingFile:
	push ax
	push bx
	mov ah, 0Eh
	mov al, '.'
	mov bl, 0Fh
	int 10h
	pop bx
	pop ax
	
	push ax
	push 1
	call ReadSector
	add sp, 4
	
	pop ax
	push ax
	call GetFATEntry
	add sp, 2
	cmp ax, 0FFFh
	jz LoadFileSuccess
	push ax
	add ax, RootDirSectors
	add ax, DeltaSectorNo
%ifdef _IN_BOOT_
	add bx, [BPB_BytsPerSec]
%else
	add bx, BPB_BytsPerSec
%endif
	jmp GoOnLoadingFile
	
LoadFileSuccess:	
	pop es
	mov ax, 0
	ret

; 根据簇号，获取文件的下一簇号，如果是0FFFh，则文件已结束
; 参数1：簇号
GetFATEntry:
	mov bp, sp
	push es
	push bx
	
	mov ax, es
	sub ax, 0100h
	mov es, ax
	
	; 第一个参数，簇号
	mov ax, [bp + 2]
	mov byte [bOdd], 0
	mov bx, 3
	mul bx
	mov bx, 2
	div bx
	cmp dx, 0
	jz LABEL_EVEN
	mov byte [bOdd], 1
LABEL_EVEN:
	xor dx, dx
%ifdef _IN_BOOT_
	mov bx, [BPB_BytsPerSec]
%else
	mov bx, BPB_BytsPerSec
%endif
	div bx
	
	push dx
	mov bx, 0
	add ax, SectorNoOfFAT1
	push ax
	push 2
	call ReadSector
	add sp, 4
	
	pop dx
	add bx, dx
	mov ax, [es:bx]
	cmp byte[bOdd], 1
	jnz LABEL_EVEN_2
	shr ax, 4
LABEL_EVEN_2:
	and ax, 0FFFh
	
	pop bx
	pop es
	
	ret